package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"

	jira "gopkg.in/andygrunwald/go-jira.v1"
)

var (
	configPath string
)

func init() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
	flag.StringVar(&configPath, "config", "./team.json", "-config=xx.json")
	gConf.Jira.User = os.Getenv("JIRA_USER")
	gConf.Jira.Passwd = os.Getenv("JIRA_PASSWD")
}

func GetAllIssues(client *jira.Client, searchString string) ([]jira.Issue, error) {
	last := 0
	var issues []jira.Issue
	for {
		opt := &jira.SearchOptions{
			MaxResults: 1000, // Max results can go up to 1000
			StartAt:    last,
		}

		chunk, resp, err := client.Issue.Search(searchString, opt)
		if err != nil {
			return nil, err
		}

		total := resp.Total
		if issues == nil {
			issues = make([]jira.Issue, 0, total)
		}
		issues = append(issues, chunk...)
		last = resp.StartAt + len(chunk)
		if last >= total {
			return issues, nil
		}
	}

}

func main() {
	flag.Parse()
	if configPath == "" {
		log.Fatal("miss config path")
	}
	LoadConfig(configPath)
	jiraConf := gConf.Jira
	tp := jira.BasicAuthTransport{
		Username: jiraConf.User,
		Password: jiraConf.Passwd,
	}

	client, err := jira.NewClient(tp.Client(), jiraConf.Endpoint)
	if err != nil {
		log.Fatal("open client", err)
	}

	projectList, _, err := client.Project.GetList()
	if err != nil {
		log.Fatal("get project list", err)
	}

	for _, p := range *projectList {
		if p.Name == jiraConf.ProjectName {
			jiraConf.ProjectKey = p.Key
			break
		}
	}
	boardList, _, err := client.Board.GetAllBoards(&jira.BoardListOptions{
		Name: jiraConf.BoardName,
	})
	if err != nil {
		log.Fatal("get board list", err)
	}

	for _, b := range boardList.Values {
		sprints, _, err := client.Board.GetAllSprints(fmt.Sprint(b.ID))
		if err != nil {
			log.Fatal("get sprint list", err)
		}
		for _, sprint := range sprints {
			if sprint.Name == jiraConf.SprintName {
				jiraConf.SprintID = sprint.ID
				break
			}
		}
	}

	jql := fmt.Sprintf("project = %s and Sprint = %d", jiraConf.ProjectKey, jiraConf.SprintID)
	issues, err := GetAllIssues(client, jql)
	if err != nil {
		log.Fatal("get issue", err)
	}

	ownM := make(map[string]string)
	for teamName, peoples := range gConf.Team {
		for _, peopleName := range peoples {
			ownM[peopleName] = teamName
		}
	}
	resultM := make(map[string][]*OutJiraInfo)
	for _, issue := range issues {
		ownerName := issue.Fields.Creator.DisplayName
		assigneeName := "未分配处理人"
		if issue.Fields.Assignee != nil {
			ownerName = issue.Fields.Assignee.DisplayName
			assigneeName = issue.Fields.Assignee.DisplayName
		}
		ownerName = getRealName(ownerName)
		assigneeName = getRealName(assigneeName)

		summary := issue.Fields.Summary
		state := issue.Fields.Status.Name
		ownTeam := ownM[ownerName]
		resultM[ownTeam] = append(resultM[ownTeam], &OutJiraInfo{
			JiraName:     issue.Key,
			AssigneeName: assigneeName,
			Summary:      summary,
			State:        state,
		})
	}
	for teamName, infos := range resultM {
		fmt.Printf("# %s\n\n", teamName)
		m := make(map[string]bool)
		fmt.Printf("|jira|summary|assignee|state|\n")
		fmt.Printf("|-----|------|--------|--------|\n")
		for _, info := range infos {
			uniqueKey := info.Summary
			pos := strings.Index(uniqueKey, "--Fail")
			if pos != -1 {
				uniqueKey = uniqueKey[:pos]
			}
			if m[uniqueKey] {
				continue
			}
			m[uniqueKey] = true
			fmt.Printf("|%s|%s|%s|%s|\n", info.JiraName, info.Summary, info.AssigneeName, info.State)
		}
		fmt.Println()
	}
}

type OutJiraInfo struct {
	JiraName     string
	AssigneeName string
	Summary      string
	State        string
}
